package com.example.function.integration.aop;

import com.example.function.integration.annotation.DataSource;
import com.example.function.integration.config.datasource.DataSourceContextHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @Description：定义数据库数据源切换的切面，在方法执行前根据方法上的注解切换数据源
 * @Author：fengcheng
 * @Date：2024/11/8 09:45
 */
@Aspect
@Component
@Order(1)
public class DataSourceAspect {

    /**
     * @Description：定义拦截规则，拦截com.example.function.integration.mapper包下的所有方法
     * @Author：fengcheng
     * @Date：2024/11/8 09:45
     * @Param：joinPoint
     * @ParamsType：[org.aspectj.lang.JoinPoint]
     * @Return：void
     */
    @Before("execution(public * com.example.function.integration.mapper..*(..)))")
    public void setDataSource(JoinPoint joinPoint) {
            Signature signature = joinPoint.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            Method method = methodSignature.getMethod();
            if (method.isAnnotationPresent(DataSource.class)) {
                DataSource dataSource = method.getAnnotation(DataSource.class);
                String value = dataSource.value();
                DataSourceContextHolder.setDataSource(value); // 切换至指定的数据源
            }
    }

    /**
     * @Description：清楚数据源的上下文，避免内存泄漏
     * @Author：fengcheng
     * @Date：2024/11/8 09:51
     */
    @After("execution(public * com.example.function.integration.mapper..*(..)))")
    public void restoreDataSource() {
        DataSourceContextHolder.clearDataSource();
    }

}